
#ifndef KML_SEGMENTS_H__
#define KML_SEGMENTS_H__

#include "gps_proto_util.h"
#include "kml/convenience/convenience.h"
#include "kml/dom.h"
#include "kml/engine.h"

namespace gps_proto {

class KmlSegments {
 public:
  static kmldom::DocumentPtr CreateDocument(const GpsProto& gps_proto) {
    kmldom::DocumentPtr document(
        kmldom::KmlFactory::GetFactory()->CreateDocument());
    for (int t = 0; t < gps_proto.track_size(); ++t) {
      for (int s = 0; s < gps_proto.track(t).segment_size(); ++s) {
        AddSegment(gps_proto.track(t).segment(s), 10, document);
      }
    }
    return document;
  }

  static kmldom::CoordinatesPtr CreateSegmentCoordinates(
     const SegmentProto& segment) {
    kmldom::KmlFactory* kml_factory(kmldom::KmlFactory::GetFactory());
    kmldom::CoordinatesPtr coordinates(kml_factory->CreateCoordinates());
    for (int s = 0; s < segment.point_size(); ++s) {
      const PointProto& point = segment.point(s);
      coordinates->add_latlngalt(point.lat(), point.lon(), point.ele());
    }
    return coordinates;
  }

  static kmldom::CoordinatesPtr CreateBoundsCoordinates(
      const kmldom::CoordinatesPtr& coordinates) {
    kmlengine::Bbox bbox;
    kmlengine::GetCoordinatesBounds(coordinates, &bbox);
    kmldom::KmlFactory* kml_factory(kmldom::KmlFactory::GetFactory());
    kmldom::CoordinatesPtr bounds_coordinates(kml_factory->CreateCoordinates());
    bounds_coordinates->add_latlng(bbox.get_north(), bbox.get_east());
    bounds_coordinates->add_latlng(bbox.get_north(), bbox.get_west());
    bounds_coordinates->add_latlng(bbox.get_south(), bbox.get_west());
    bounds_coordinates->add_latlng(bbox.get_south(), bbox.get_east());
    bounds_coordinates->add_latlng(bbox.get_north(), bbox.get_east());
    return bounds_coordinates;
  }

  static void AddSegment(const SegmentProto& segment, int min_points,
                         kmldom::DocumentPtr document) {
    if (segment.point_size() < min_points) {
      return;
    }
    BoundsProto bounds;
    ComputeSegmentBounds(segment, &bounds);
    const PointProto& point0 = segment.point(0);
    const PointProto& pointn = segment.point(segment.point_size() - 1);
    kmldom::KmlFactory* kml_factory(kmldom::KmlFactory::GetFactory());
    kmldom::PlacemarkPtr placemark(kml_factory->CreatePlacemark());
    kmldom::MultiGeometryPtr multigeometry(kml_factory->CreateMultiGeometry());

    // Point for first point in segment.
    kmldom::PointPtr point(
        kmlconvenience::CreatePointLatLon(point0.lat(), point0.lon()));
    multigeometry->add_geometry(point);

    // LineString with vertex at each point in the segment.
    kmldom::LineStringPtr linestring(kml_factory->CreateLineString());
    linestring->set_coordinates(CreateSegmentCoordinates(segment));
    multigeometry->add_geometry(linestring);

    // Polygon of n,s,e,w bounds of points in segment.
    kmldom::LinearRingPtr linearring(kml_factory->CreateLinearRing());
    linearring->set_coordinates(
        CreateBoundsCoordinates(linestring->get_coordinates()));
    kmldom::OuterBoundaryIsPtr outer(kml_factory->CreateOuterBoundaryIs());
    outer->set_linearring(linearring);
    kmldom::PolygonPtr polygon(kml_factory->CreatePolygon());
    polygon->set_outerboundaryis(outer);
    multigeometry->add_geometry(polygon);
                        
    placemark->set_geometry(multigeometry);
    placemark->set_styleurl("style.kml#point_line_poly");

/*
    kmlconvenience::AddExtendedDataValue(const std::string& name, const std::string& value,
                          kmldom::FeaturePtr feature);

    kmldom::PlacemarkPtr placemark
                  << gps_proto::DateTime::ToDateTime(segment.point(0).time())
                  << ", "
                  << segment.point(num_points-1).time() -
                     segment.point(0).time()
                  << " seconds, "
                  << num_points
                  << " points " << std::endl;
*/
    document->add_feature(placemark);
  }

};

}  // namespace gps_proto

#endif  // KML_SEGMENTS_H__
